package com.uobgroup.ews.uam.core.dao;

import java.util.List;

import javax.persistence.Query;

import org.springframework.stereotype.Repository;

import com.uobgroup.ews.uam.core.domain.ReferenceType;
import com.uobgroup.ews.uam.core.enums.ScopeType;

@Repository
public class ReferenceTypeDaoImpl extends AbstractJpaDao<ReferenceType> implements ReferenceTypeDao {

   
   @SuppressWarnings("unchecked")
   @Override
   public ReferenceType findReferenceTypeThatHasNameAndNotHasId(String name, Long id) {
      Query query = entityManager.createQuery("SELECT o FROM ReferenceType o where lower(o.name) = :name and o.id != :id", 
            ReferenceType.class);
      query.setParameter("name", name.toLowerCase());
      query.setParameter("id", id);
      List<ReferenceType> referenceTypes = query.getResultList();
      if (referenceTypes.isEmpty())
         return null;
      ReferenceType reference = referenceTypes.get(0);
      return reference;
   }

   @SuppressWarnings("unchecked")
   @Override
   public ReferenceType findReferenceTypeThatHasCodeAndNotHasId(String code, Long id) {
      Query query = entityManager.createQuery("SELECT o FROM ReferenceType o where lower(o.code) = :code and o.id != :id", 
            ReferenceType.class);
      query.setParameter("code", code.toLowerCase());
      query.setParameter("id", id);
      List<ReferenceType> referenceTypes = query.getResultList();
      if (referenceTypes.isEmpty())
         return null;
      ReferenceType reference = referenceTypes.get(0);
      return reference;
   }

   /**
    * use to check exist code
    */
   @SuppressWarnings("unchecked")
   @Override
   public ReferenceType findReferenceTypeByCode(String code) {
      Query query = entityManager.createQuery("SELECT o FROM ReferenceType o where lower(o.code) = :code", 
            ReferenceType.class);
      query.setParameter("code", code.toLowerCase());
      List<ReferenceType> referenceTypes = query.getResultList();
      if (referenceTypes.isEmpty())
         return null;
      ReferenceType reference = referenceTypes.get(0);
      return reference;
   }
   
   /**
    * use to check exist name
    */
   @SuppressWarnings("unchecked")
   @Override
   public ReferenceType findReferenceTypeByName(String name) {
      Query query = entityManager.createQuery("SELECT o FROM ReferenceType o where lower(o.name) = :name", 
            ReferenceType.class);
      query.setParameter("name", name.toLowerCase());
      List<ReferenceType> referenceTypes = query.getResultList();
      if (referenceTypes.isEmpty())
         return null;
      ReferenceType reference = referenceTypes.get(0);
      return reference;
   }
   
   /**
    * get type by code and scope, use in create action in Segment Controller
    */
   @SuppressWarnings("unchecked")
   @Override
   public ReferenceType findReferenceTypeByCodeAndScope(String code, ScopeType scope) {
      Query query = entityManager.createQuery("SELECT o FROM ReferenceType o where lower(o.code) = :code AND o.scope = :scope", 
            ReferenceType.class);
      query.setParameter("code", code.toLowerCase());
      query.setParameter("scope", scope);
      List<ReferenceType> referenceTypes = query.getResultList();
      if (referenceTypes.isEmpty())
         return null;
      ReferenceType reference = referenceTypes.get(0);
      return reference;
   }
   /**
    * use to check exist name
    */
   @SuppressWarnings("unchecked")
   @Override
   public ReferenceType findReferenceTypeByNameAndScope(String name, ScopeType scope) {
      Query query = entityManager.createQuery("SELECT o FROM ReferenceType o where lower(o.name) = :name AND o.scope = :scope", 
            ReferenceType.class);
      query.setParameter("name", name.toLowerCase());
      query.setParameter("scope", scope);
      List<ReferenceType> referenceTypes = query.getResultList();
      if (referenceTypes.isEmpty())
         return null;
      ReferenceType reference = referenceTypes.get(0);
      return reference;
   }
   /**
    * use to count all reference types when display in list
    */
   @Override
   public long countReferenceTypesByScope(ScopeType scope) {
      return entityManager.createNamedQuery(ReferenceType.QUERY_COUNT_REFERENCE_TYPE_BY_SCOPE, Long.class)
            .setParameter(ReferenceType.PARAM_SCOPE, scope).getSingleResult();
   }
   /**
    * use to get data and bind data to drop down
    */
   @SuppressWarnings("unchecked")
   @Override
   public List<ReferenceType> findReferenceTypesByScope(ScopeType scope) {
      Query query = entityManager.createNamedQuery(ReferenceType.QUERY_FIND_REFERENCE_TYPE_BY_SCOPE);
      query.setParameter(ReferenceType.PARAM_SCOPE, scope);
      List<ReferenceType> results = (List<ReferenceType>) query.getResultList();
      return results;
   }
   /**
    * use to get data for list of reference types 
    */
   @SuppressWarnings("unchecked")
   @Override
   public List<ReferenceType> findReferenceTypesByScope(ScopeType scope, int firstResult, int maxResults) {
      Query query = entityManager.createNamedQuery(ReferenceType.QUERY_FIND_REFERENCE_TYPE_BY_SCOPE);
      query.setParameter(ReferenceType.PARAM_SCOPE, scope);
      query.setFirstResult(firstResult).setMaxResults(maxResults);
      List<ReferenceType> results = (List<ReferenceType>) query.getResultList();
      return results;
   }

   public ReferenceTypeDaoImpl() {
      setClazz(ReferenceType.class);
   }
   
   /**
    * use to get data to show application role or security role
    */
   @SuppressWarnings("unchecked")
   @Override
   public ReferenceType findReferenceTypeByIdAndScope(Long id, ScopeType scope) {
      Query query = entityManager.createNamedQuery(ReferenceType.QUERY_FIND_REFERENCE_TYPE_BY_ID_AND_SCOPE);
      query.setParameter(ReferenceType.PARAM_SCOPE, scope);
      query.setParameter(ReferenceType.PARAM_ID, id);
      List<ReferenceType> referenceTypes = query.getResultList();
      if (referenceTypes.isEmpty())
         return null;
      ReferenceType reference = referenceTypes.get(0);
      return reference;
   }
   
}
